package org.jeecg.modules.iot.aio;

import com.aliyuncs.iot.model.v20180120.PubResponse;
import org.jeecg.modules.iot.aio.task.CheckMessageRunnable;
import org.jeecg.modules.iot.aliyun.MessageBody;
import org.jeecg.modules.iot.common.IotConst;
import org.jeecg.modules.iot.message.ReceivePopupIndex;
import org.jeecg.modules.iot.message.ReceivePopupSN;
import org.jeecg.modules.iot.message.ReceiveUpload;
import org.jeecg.modules.iot.serialport.SerialPortData;
import org.jeecg.modules.iot.serialport.SerialPortException;
import org.tio.utils.lock.MapWithLock;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Objects;

/**
 * 设备
 *
 * @author scw
 * @version v1.0
 * @date
 */
public class ChannelContext {

    public AioConfiguration aioConfiguration;

    /**
     * sn弹出结果
     * key为 {@link AioConst.sn}
     */
    private MapWithLock<String, ReceivePopupSN>  popupSN = new MapWithLock<>(new HashMap<String, ReceivePopupSN>());
    /**
     * 空位弹出结果
     * key为 {@link AioConst.hole}
     */
    private MapWithLock<String, ReceivePopupIndex> popupHole = new MapWithLock<>(new HashMap<String, ReceivePopupIndex>());


    private String firstConnectTime = "";
    /**
     * 阿里云产品KEY
     */
    private String productKey;
    /**
     * 设备mac
     */
    private String deviceMac;

    private boolean hasError = false;

    private String errorMessage = "";
    /**
     * 查询设备
     */
    public CheckMessageRunnable checkMessageRunnable = null;

    /**
     * 设备的sn
     */
    private String rentboxSN;
    /**
     * check结束标志
     */
    public boolean isCheck = false;
    /**
     * check超时时间
     */
    public Long checkExpireTime = 0L;
    /**
     * check结束后需要查询MNS获取消息
     */
    public boolean needQuery = false;
    /**
     * check 响应
     */
    public PubResponse response = null;
    /**
     * 查询响应
     */
    private ReceiveUpload receiveUpload;

    public static final String UNKNOWN_ADDRESS_IP = "$UNKNOWN";

    public ChannelContext(AioConfiguration aioConfiguration,String sn){
        this.aioConfiguration = aioConfiguration;
        this.firstConnectTime = LocalDateTime.now().toString();
        this.rentboxSN = sn;
        this.aioConfiguration.queueList.bind(this);
        this.productKey = aioConfiguration.getProductKey();
        this.checkMessageRunnable = new CheckMessageRunnable(this.aioConfiguration.aioExecutor,this);

    }

    /**
     * 记录相关查询的结果
     * @param messageBody
     */
    public void addMNSMessage(MessageBody messageBody){

        String messageType = messageBody.getMessageType();
        if(Objects.equals(messageType,"upload")) {
            int cmd = SerialPortData.checkCMD(messageBody.getPayloadAsBytes());
            byte[] data = messageBody.getPayloadAsBytes();
            switch (cmd) {
                case 0x10:  //check  check_all
                    try {
                        this.receiveUpload = new ReceiveUpload(data);
                    } catch (SerialPortException e) {
                        this.errorMessage = e.getMessage();
                    }
                    break;
                case 0x21: //孔位弹出
                    try {
                        ReceivePopupIndex receivePopupIndex = new ReceivePopupIndex(data);
                        String key = String.format(AioConst.hole, receivePopupIndex.getPowerbankIndex());
                        this.popupHole.put(key, receivePopupIndex);
                    } catch (SerialPortException e) {
                        this.errorMessage = e.getMessage();
                    }
                    break;
                case 0x31: //popup by sn
                    try {
                        ReceivePopupSN receivePopupSN = new ReceivePopupSN(data);
                        String key = String.format(AioConst.sn, receivePopupSN.getSnAsString());
                        this.popupSN.put(key, receivePopupSN);
                    } catch (SerialPortException e) {
                        this.errorMessage = e.getMessage();
                    }
                    break;
            }
        }

    }

    /**
     * 获取当前孔位的弹出结果
     * @param hole
     * @return
     */
    public ReceivePopupIndex getPopupIndexResult(String hole){
        if(hole == null)return null;
        String key = String.format(AioConst.hole,hole);
        /**拿到结果后删除*/
        this.popupHole.remove(key);
        return this.popupHole.get(key);
    }

    /**
     * 获取当前SN的弹出结果
     * @param sn
     * @return
     */
    public ReceivePopupSN getPopupSnResult(String sn){
        if(sn == null)return null;
        String key = String.format(AioConst.sn,sn);
        ReceivePopupSN result = this.popupSN.get(key);
        /**拿到结果后删除*/
        this.popupSN.remove(key);
        return result;
    }


    public String getDeviceMac() {
        return deviceMac;
    }

    public String getProductKey() {
        return productKey;
    }
    public String getRentboxSN() {
        return rentboxSN;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public ReceiveUpload getReceiveUpload() {
        return receiveUpload;
    }

    public void setReceiveUpload(ReceiveUpload receiveUpload) {
        this.receiveUpload = receiveUpload;
    }

    public void setDeviceMac(String deviceMac) {
        this.deviceMac = deviceMac;
    }
}
